package com.fzj.example.socket.tcp.nonblock.nio;

import com.sun.security.ntlm.Server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 * ClassName: ChatRoomServer
 * date: 2019/11/21 14:05
 * Description:
 * 功能1： 客户端通过Java NIO连接到服务端，支持多客户端的连接
 * 功能2：客户端初次连接时，服务端提示输入昵称，如果昵称已经有人使用，提示重新输入，如果昵称唯一，则登录成功，之后发送消息都需要按照规定格式带着昵称发送消息
 * 功能3：客户端登录后，发送已经设置好的欢迎信息和在线人数给客户端，并且通知其他客户端该客户端上线
 * 功能4：服务器收到已登录客户端输入内容，转发至其他登录客户端。
 * 功能5 TODO：客户端下线检测  方案是：客户端在线的时候发送心跳，服务端用TimeCacheMap自动删除过期对象，同时通知线上用户删掉的用户下线
 * @author fanzj@bonree.com
 * @since JDK 1.8
 */
public class ChatRoomServer {
    private Selector selector;
    private int port=9999;
    private Charset charset=Charset.forName("UTF-8");
    private static HashSet<String> users=new HashSet<>();

    public void init() throws IOException {
        selector=Selector.open();
        ServerSocketChannel ssc= ServerSocketChannel.open();
        ssc.bind(new InetSocketAddress(port));
        ssc.configureBlocking(false);
        ssc.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("服务端已启动");
        while (true){
            int num=selector.select();
            if(num==0) continue;
            Set< SelectionKey > setKey = selector.selectedKeys();
            setKey.stream().forEach(selectionKey -> {
                //切记要去掉已经处理的，不然后续会报错
                setKey.remove(selectionKey);
                //
                try {
                    doWithSelectionKey(ssc,selectionKey);
                } catch (IOException e) {
                    selectionKey.channel();
                    if(selectionKey.channel()!=null){
                        try {
                            selectionKey.channel().close();
                        } catch (IOException e1) {
                            e1.printStackTrace();
                        }
                    }
                    e.printStackTrace();
                }
            });
        }
    }

    private void doWithSelectionKey(ServerSocketChannel ssc, SelectionKey selectionKey) throws IOException {
        if(selectionKey.isAcceptable()){
            SocketChannel sc=ssc.accept();
            sc.configureBlocking(false);
            sc.register(selector,SelectionKey.OP_READ);
            System.out.println("远程地址"+sc.getRemoteAddress());
            sc.write(charset.encode("请输入你的名字:"));
        }
        if(selectionKey.isReadable()){
            SocketChannel sc= (SocketChannel) selectionKey.channel();
            ByteBuffer dst=ByteBuffer.allocate(1024);
            StringBuilder msg=new StringBuilder();
            int len;
            while ((len=sc.read(dst))>0){
                dst.flip();
                msg.append(charset.decode(dst));

            }
            System.out.println("服务端收到信息："+msg);

        }
        if(selectionKey.isReadable()){

        }
    }


}
